package com.eagle.roomsearch.util;

import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Random;

/**
 * @author SQG
 * @version 1.0
 * @time 2017年12月19日 下午3:53:50
 **/
public class AESUtil {

    protected static final Logger log = Logger.getLogger(AESUtil.class);

    private byte[] initVector = {0x32, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x38, 0x27, 0x36, 0x35, 0x33, 0x23,
            0x32, 0x31};

    /**
     * FIXME For demo only, should rewrite this method in your product
     * environment!
     *
     * @param appid
     * @return
     */
    public static String findKeyById(String appid) {
        // Fake key.
        String key = "12345678901234567890123456789012";
        return key;
    }

    // 加密
    public static String Encrypt(String sSrc, String sKey) throws Exception {
        if (sKey == null) {
            System.out.print("Key为空null");
            return null;
        }
        // 判断Key是否为16位
        if (sKey.length() != 16) {
            System.out.print("Key长度不是16位");
            return null;
        }
        byte[] raw = sKey.getBytes();
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// "算法/模式/补码方式"
        // IvParameterSpec iv = new
        // IvParameterSpec("0102030405060708".getBytes());//使用CBC模式，需要一个向量iv，可增加加密算法的强度
        // cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes());
        // System.out.println(encrypted.length);

        return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码功能，同时能起到2次加密的作用。
    }

    // 解密
    public static String decrypt(String sSrc, String sKey) throws Exception {
        try {
            // 判断Key是否正确
            if (sKey == null) {
                System.out.print("Key为空null");
                return null;
            }
            // 判断Key是否为16位
            if (sKey.length() != 16) {
                System.out.print("Key长度不是16位");
                return null;
            }
            byte[] raw = sKey.getBytes("UTF-8");
            SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());
            // cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
            try {
                byte[] original = cipher.doFinal(encrypted1);
                String originalString = new String(original);
                return originalString;
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println(e.toString());
                return null;
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println(ex.toString());
            return null;
        }
    }

    /**
     * 创建16位密钥
     *
     * @return
     * @author SQG
     * @time 2018年1月18日 上午11:10:32
     */
    public static String createSKey() {
        int maxNum = 36;
        int i;
        int count = 0;
        char[] str = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
                'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
        StringBuffer pwd = new StringBuffer("");
        Random r = new Random();
        while (count < 16) {
            i = Math.abs(r.nextInt(maxNum));
            if (i >= 0 && i < str.length) {
                pwd.append(str[i]);
                count++;
            }
        }
        String sKey = pwd.toString();
        return sKey;
    }

    /**
     * 创建16位密钥
     *
     * @return
     * @author SQG
     * @time 2018年1月18日 上午11:10:32
     */
    public static byte[] createSKeyToByte() {
        String skey = AESUtil.createSKey();
        return skey.getBytes();
    }

    // public static void main(String[] args) throws Exception {
    // /*
    // * 加密用的Key 可以用26个字母和数字组成，最好不要用保留字符，虽然不会错，至于怎么裁决，个人看情况而定
    // * 此处使用AES-128-CBC加密模式，key需要为16位。
    // */
    //// String cKey = "bawcVudH+uA6z4xokeQo4NlqpCtZFRqem1kl/J2Vra8=";
    //// String cKey = "bawcVudH+uA6z4xo";
    // String cKey = "0908TSG9R7X8A6RQ";
    // byte[] bytes = cKey.getBytes();
    // System.out.println(bytes.length);
    // // 需要加密的字串
    // String cSrc = "{\"CmdType\":20,\"username\":\"test\"}";
    // System.out.println(cSrc);
    // // 加密
    // long lStart = System.currentTimeMillis();
    // String enString = AESUtil.Encrypt(cSrc, cKey);
    // System.out.println("加密后的字串是：" + enString);
    //
    // long lUseTime = System.currentTimeMillis() - lStart;
    // System.out.println("加密耗时：" + lUseTime + "毫秒");
    // // 解密
    // lStart = System.currentTimeMillis();
    // String DeString =
    // AESUtil.decrypt("wn8w9Cv+fq5Wb2iNf7T2czZhJlJAPlXPJObRGh1djtXztN5NzPIf99HZmgau8m1u",
    // cKey);
    // System.out.println("解密后的字串是：" + DeString);
    // lUseTime = System.currentTimeMillis() - lStart;
    // System.out.println("解密耗时：" + lUseTime + "毫秒");
    // }
}
